import {
  ALL,
  Del,
  Get,
  HttpCode,
  Inject,
  Param,
  Put,
  Query,
  Validate,
} from '@midwayjs/decorator';
import { Body, Controller, Post, Provide } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';
import { CreateApiDoc } from '@midwayjs/swagger';
import { ChangePasswordDto, UserDto } from '../dto';
import { User } from '../entity/User';
import { IBaseQuery } from '../interface';
import * as _ from 'lodash';
import { Repository } from 'typeorm';
import { InjectEntityModel } from '@midwayjs/orm';

@Provide()
@Controller('/users', { tagName: '用户管理' })
export class UserController {
  @Inject()
  ctx: Context;

  @InjectEntityModel(User)
  userModel: Repository<User>;

  @Get('/', { summary: '获取用户列表' })
  async index(@Query(ALL) query: IBaseQuery) {
    const [rows, count] = await this.userModel.findAndCount({
      where: _.omit(query, ['offset', 'limit']),
      skip: query.offset || 0,
      take: query.limit || 10,
    });
    return { rows, count };
  }

  @(CreateApiDoc()
    .respond(200, 'ok', 'json', { example: { nickname: 'xxx' } })
    .build())
  @Post('/', { middleware: ['jwt'], summary: '创建用户' })
  @Validate()
  async create(@Body(ALL) body: UserDto): Promise<User> {
    // 检查用户名是否重复
    const isExist = await this.userModel.findOne({
      username: body.username,
    });
    if (isExist) {
      this.ctx.throw(400, '用户名已存在');
    }
    const user = await this.userModel.create(body);
    await this.userModel.save(user);
    return user;
  }

  @Get('/:id', { summary: '获取用户详情' })
  async show(@Param() id: number): Promise<User> {
    const user = await this.userModel.findOne(id);
    return user;
  }

  @Put('/:id', { summary: '更新用户' })
  async update(@Param() id: number, @Body(ALL) body: UserDto): Promise<User> {
    const user = await this.userModel.findOne(id);
    this.userModel.merge(user, body);
    await this.userModel.save(user);
    return user;
  }

  @Put('/changePassword', { middleware: ['jwt'], summary: '修改用户密码' })
  @Validate()
  async changePassword(@Body(ALL) body: ChangePasswordDto) {
    const state = this.ctx.state;
    const user = await this.userModel.findOne(state.user.id);
    if (!user.validatePassword(body.password)) {
      this.ctx.throw(400, '用户名或密码错误');
    }
    user.changePassword(body.newPassword);
    await this.userModel.save(user);
    return { message: '修改成功' };
  }

  @Del('/:id', { middleware: ['jwt'], summary: '删除用户' })
  @HttpCode(204)
  async delete(@Param() id: number) {
    const user = await this.userModel.findOne(id);
    if (user) {
      await this.userModel.softRemove(user);
    }
  }
}
